package com.blacktry.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.blacktry.entity.blog.Articles;
import com.blacktry.entity.model.Vo.BlogVo;
import com.blacktry.entity.model.request.ArticlesRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.swing.text.Highlighter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class BLogESService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ArticlesService articlesService;

    // 1.解析数据放入 es 中   BulkRequest用于把导入批量数据
    public Boolean parseContent() throws Exception {
        List<BlogVo> contents = articlesService.findAllForES();
        // 把查询的数据放入es中
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("2m");

        //检测是否存在 blogs
        GetIndexRequest request = new GetIndexRequest("blogs");
        boolean exists =restHighLevelClient.indices()
                .exists(request, RequestOptions.DEFAULT);
        //如果不存在 blogs 索引，就创建一个 blogs 索引      jd_goods
        if (!exists) {
            CreateIndexRequest createIndexRequest = new CreateIndexRequest("blogs");
            CreateIndexResponse createIndexResponse1 =
                    restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        }
         //将查询出的数据添加到es中
        for (int i = 0;i < contents.size();i++) {
//            如果不设置id的话 会生成一个随机id 此处没有设置id
            bulkRequest.add(new IndexRequest("blogs").source(JSON.toJSONString(contents.get(i)), XContentType.JSON));
        }
        //  客户端操作  执行请求
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
//        bulk.hasFailures  是否失败
        return !bulk.hasFailures();
    }



    // 2.到es中查询分页获取这些数据
    public List<Map<String, Object>> HighSearchPage(ArticlesRequest articlesRequest, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }
        // 条件搜索  设置了搜索的是哪个索引
        SearchRequest searchRequest = new SearchRequest("blogs");
        //构建搜索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 匹配
        if(!StrUtil.isBlank(articlesRequest.getMessage())){
            MatchQueryBuilder queryBuilder1 = QueryBuilders.matchQuery("articleTitle", articlesRequest.getMessage());
            MatchQueryBuilder queryBuilder2 = QueryBuilders.matchQuery("articleDescription", articlesRequest.getMessage());
            boolQueryBuilder.should(queryBuilder1);
            boolQueryBuilder.should(queryBuilder2);
        }
        if(!StrUtil.isBlank(articlesRequest.getSort())) {
            TermQueryBuilder queryBuilder3 = QueryBuilders.termQuery("articleTitle",articlesRequest.getSort());
            boolQueryBuilder.must(queryBuilder3);
        }
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//设置时间
        //高亮
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("articleTitle");
        highlightBuilder.field("articleDescription");
        highlightBuilder.requireFieldMatch(false); //多个显示高亮此处开启
        highlightBuilder.preTags("<span style='color:green'>");
        highlightBuilder.postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);

        // 执行搜索
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        // 解析结果
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //结果封装成高亮

            Map<String, HighlightField> highlightFields=hit.getHighlightFields();
            HighlightField articleTitle=highlightFields.get("articleTitle");
            HighlightField articleDescription=highlightFields.get("articleDescription");

            Map<String,Object> sourceAsMap =hit.getSourceAsMap(); //这是原来的结果
            //解析高亮的字段  将原来的字段换成高亮的字段
            if(articleTitle!=null){
                Text[] fragmentsArticleTitle=articleTitle.fragments();
                Text[] fragmentsArticleDescription=articleDescription.fragments();
                String n_title="";
                String n_desc="";
                for(Text text:fragmentsArticleTitle){
                    n_title += text;
                }
                for(Text text:fragmentsArticleDescription){
                    n_desc += text;
                }
                sourceAsMap.put("articleTitle",n_title);//高亮字段替换到原来的内容即可
                sourceAsMap.put("articleDescription",n_desc);//高亮字段替换到原来的内容即可
            }
            list.add(sourceAsMap);
        }
        return list;
    }






    public CreateIndexResponse createIndex() throws IOException {
        //创建索引请求
        CreateIndexRequest request = new CreateIndexRequest("blogs");
        //利用restHighLevelClient创建IndicesClient用于执行API
        IndicesClient indicesClient = restHighLevelClient.indices();
        //执行请求
//        CreateIndexResponse response = indicesClient.create(request, RequestOptions.DEFAULT);
        CreateIndexResponse response = indicesClient.create(request, RequestOptions.DEFAULT);
        System.out.println(response);
        return response;
    }
}